/**
 * Copyright 2010 ArcBees Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.arcbees.hive.client.home.slogan;

import com.arcbees.hive.client.home.slogan.SloganPresenter.MyView;
import com.arcbees.hive.client.home.slogan.SloganView.MyUiHandlers;
import com.arcbees.hive.client.mvp.ViewWithUiHandlers;
import com.arcbees.hive.client.mvp.strategies.UiHandlersStrategy;

import static com.google.gwt.query.client.GQuery.$;

import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.query.client.Function;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;

import com.gwtplatform.mvp.client.UiHandlers;

/**
 * @author Christian Goudreau
 * @author Zachary Keatts
 */
public class SloganView extends ViewWithUiHandlers<MyUiHandlers> implements
    MyView {
  /**
   * This will provide a way to automatically create and inject the
   * {@link com.gwtplatform.mvp.client.View} instead of using directly
   * <code>gwt.create()</code>. You only have to inject it in the ctor.
   */
  public interface Binder extends UiBinder<Widget, SloganView> {
  }

  /**
   * {@link SloganView}'s UiHandlers.
   * 
   * @see com.arcbees.hive.client.home.slogan.SloganPresenter#showDescription()
   */
  public interface MyUiHandlers extends UiHandlers {
    /**
     * When a mouseover event on a descriptor is over, or the mouse leaves the
     * affected area the description should return to the original default. This
     * will manage the change back to default and any special effects associated
     * with it.
     * 
     * @see com.arcbees.hive.client.home.slogan.SloganPresenter#fadeDescription()
     */
    void defaultDescription();

    /**
     * When a mouseover on the consulting image is caught this method should be
     * called. It is in charge of managing the change from a default description
     * to the consulting description
     * 
     * @see com.arcbees.hive.client.home.slogan.SloganPresenter#fadeDescription()
     */
    void showConsulting();

    /**
     * When a mouseover on the development image is caught this method should be
     * called. It is in charge of managing the change from a default description
     * to the consulting description
     * 
     * @see com.arcbees.hive.client.home.slogan.SloganPresenter#fadeDescription()
     */
    void showDevelopment();

    /**
     * When a mouseover on the success image is caught this method should be
     * called. It is in charge of managing the change from a default description
     * to the consulting description
     * 
     * @see com.arcbees.hive.client.home.slogan.SloganPresenter#fadeDescription()
     */
    void showSuccess();

    void showConsultingSection();

    void showDevelopmentSection();

    void showSuccessStorySection();
  }

  @UiField
  HTML fadeBlockOne;
  @UiField
  HTML fadeBlockTwo;

  private Integer actualFadeCount = 0;
  private Integer fadeToCount = 2;
  private Integer fadeDelay = 250;
  private Boolean blockFade = false;
  private SafeHtml lastDescription = null;
  private Boolean click = false;

  /**
   * {@link Function} that insure that we wait until every fade animation is
   * finished before unblocking upcoming fade animation.
   */
  private Function fadeFunction = new Function() {
    @Override
    public void f(Element e) {
      actualFadeCount++;

      if (actualFadeCount.equals(fadeToCount)) {
        actualFadeCount = 0;

        blockFade = false;

        if (lastDescription != null) {
          fadeDescription(lastDescription);
          lastDescription = null;
        }
      }
    }
  };

  @Inject
  public SloganView(final Binder uiBinder,
      final UiHandlersStrategy<MyUiHandlers> uiHandlersStrategy) {
    super(uiHandlersStrategy);

    initWidget(uiBinder.createAndBindUi(this));
  }

  @Override
  public void fadeDescription(SafeHtml desc) {
    // Make sure that fading effect isn't blocked.
    if (!blockFade) {
      // Make sure that the fade block we want to hide is visible and the one
      // that we want to show isn't. Also, we make sure the description
      // we want to show isn't the same as the one already shown.
      if (fadeBlockTwo.isVisible()
          && !desc.asString().equals(fadeBlockTwo.getHTML())
          && !fadeBlockOne.isVisible()) {
        switchFade(fadeBlockOne, fadeBlockTwo.getElement(), desc);

        // we make sure the description we want to show isn't the same as the
        // one
        // already shown.
      } else if (!desc.asString().equals(fadeBlockOne.getHTML())
          && !fadeBlockTwo.isVisible()) {
        switchFade(fadeBlockTwo, fadeBlockOne.getElement(), desc);
      }
    } else {
      lastDescription = desc;
    }
  }

  @UiHandler("sloganArea")
  void onSloganAreaMouseOut(MouseOutEvent e) {
    if (!click) {
      getUiHandlers().defaultDescription();
    }

    click = false;
  }

  @UiHandler("consulting")
  void onConsultingMouseOver(MouseOverEvent e) {
    getUiHandlers().showConsulting();
  }

  @UiHandler("consulting")
  void onConsultingClicked(ClickEvent e) {
    getUiHandlers().showConsultingSection();

    click = true;
  }

  @UiHandler("development")
  void onDevelopmentMouseOver(MouseOverEvent e) {
    getUiHandlers().showDevelopment();
  }

  @UiHandler("development")
  void onDevelopmentClicked(ClickEvent e) {
    getUiHandlers().showDevelopmentSection();

    click = true;
  }

  @UiHandler("success")
  void onSuccessMouseOver(MouseOverEvent e) {
    getUiHandlers().showSuccess();
  }

  @UiHandler("success")
  void onSuccessClicked(ClickEvent event) {
    getUiHandlers().showSuccessStorySection();

    click = true;
  }

  /**
   * Used to start the animation that switch the opacity of the two fade block.
   * 
   * @param fadeBlock The fade block to show.
   * @param element The {@link Element} of the second block to hide.
   * @param desc The description of the first block to set.
   */
  private void switchFade(HTML fadeBlock, Element element, SafeHtml desc) {
    blockFade = true;
    fadeBlock.setHTML(desc);

    $(fadeBlock).fadeIn(fadeDelay, fadeFunction);
    $(element).fadeOut(fadeDelay, fadeFunction);
  }
}
